#ifndef __DYNAMICCREATE_H__
#define __DYNAMICCREATE_H__

#include <vector>
#include <functional>
#include "noncopyable.h"
#include "singleton.h"
#include "anyval.h"

#define PRIVATE_REG_DYNCREATE_4(class_name, baseName1, baseName2, baseName3) \
class class_name##Register { \
private: \
    static ClassRegistor<class_name> reg_; \
}; \
ClassRegistor<class_name> class_name##Register::reg_(#class_name, #baseName1, #baseName2, #baseName3)

#define PRIVATE_REG_DYNCREATE_3(class_name, baseName1, baseName2) \
class class_name##Register { \
private: \
    static ClassRegistor<class_name> reg_; \
}; \
ClassRegistor<class_name> class_name##Register::reg_(#class_name, #baseName1, #baseName2)

#define PRIVATE_REG_DYNCREATE_2(class_name, baseName) \
class class_name##Register { \
private: \
    static ClassRegistor<class_name> reg_; \
}; \
ClassRegistor<class_name> class_name##Register::reg_(#class_name, #baseName)


#define PRIVATE_REG_DYNCREATE_1(class_name) PRIVATE_REG_DYNCREATE_2(class_name, class_name)


#define PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT(_1,_2,_3,_4,_5,_6,_7,_8,_9, N, ...) N
#define PRIVATE_MACRO_VAR_ARGS_IMPL(args)  PRIVATE_MACRO_VAR_ARGS_IMPL_COUNT args
#define COUNT_MACRO_VAR_ARGS(...)  PRIVATE_MACRO_VAR_ARGS_IMPL((__VA_ARGS__,10,9,8,7,6,5 4,3,2,1,0))

#define PRIVATE_MACRO_CHOOSE_HELPER2(M, count)  M##count
#define PRIVATE_MACRO_CHOOSE_HELPER1(M, count)  PRIVATE_MACRO_CHOOSE_HELPER2(M, count)
#define PRIVATE_MACRO_CHOOSE_HELPER(M, count)   PRIVATE_MACRO_CHOOSE_HELPER1(M, count)


//实现宏不定参数的重载
#ifdef WIN32
//EXPAND 用于解决windows上编译器将__VA_ARGS__展开成一个参数的问题
#define EXPAND(...) __VA_ARGS__
#define REG_DYNCREATE(...) EXPAND(PRIVATE_MACRO_CHOOSE_HELPER(PRIVATE_REG_DYNCREATE_, COUNT_MACRO_VAR_ARGS( __VA_ARGS__))( __VA_ARGS__))
#else
#define REG_DYNCREATE(...) PRIVATE_MACRO_CHOOSE_HELPER(PRIVATE_REG_DYNCREATE_, COUNT_MACRO_VAR_ARGS( __VA_ARGS__))( __VA_ARGS__)
#endif	
#define DYN_CREATE(objName) CObjectFactoryAgent::get_instance().CreateObject(objName) 

class CObjectFactory 
{
public:
    template<typename T>
    void RegisterObject(const char* objName)
    {
        std::function<void* ()> function = []() {
			return new T;
		};

        m_creatorMap[objName] = AnyVar(function);
    } 
    void *CreateObject(const std::string &objName)
    {
        if(m_creatorMap.find(objName) == m_creatorMap.end())
        {
            return nullptr;
        }
        AnyVar resolver = m_creatorMap[objName];
		std::function<void* ()> func = any_cast<std::function<void* ()>>(resolver);
        return func();
    }
private:
	std::map<std::string, AnyVar> m_creatorMap;
};

typedef Singleton<CObjectFactory> CObjectFactoryAgent;



//运行时类对象管理
class CRuntimeClass
{
    //运行时类对象
    struct CRuntimeNode
    {
        //类名称
        std::string m_strClassName;
        //继承类
        std::vector<CRuntimeNode*>  m_vecInherit;

    };
public:
    //判断A是B的基类
    bool IsBaseOf(const std::string& baseName, const std::string& objName)
    {
        auto itFind = m_runtimeNode.find(objName);
        if(itFind == m_runtimeNode.end())
        {
            return false;
        }
        for(auto item : itFind->second.m_vecInherit)
        {
            if(item->m_strClassName == baseName)
            {
                return true;
            }
            if(IsBaseOf(baseName, item->m_strClassName))
            {
                return true;
            }
        }
        return false;
    }

    template<typename... Args >
    void RegisterInherit(const char* objName, const char* baseName, Args... args)
    {
        CRuntimeNode& node = GetRunNode(objName);
        if(std::string(objName) != baseName)
        {
            CRuntimeNode& inhNode = GetRunNode(baseName);
            node.m_vecInherit.push_back(&inhNode);
        }
        RegisterInherit(objName, args...);
    }

    void RegisterInherit(const char* objName, const char* baseName)
    {
        CRuntimeNode& node = GetRunNode(objName);
        if(std::string(objName) != baseName)
        {
            CRuntimeNode& inhNode = GetRunNode(baseName);
            node.m_vecInherit.push_back(&inhNode);
        }
    }

    CRuntimeNode& GetRunNode(const char* objName)
    {
        if(m_runtimeNode.find(objName) == m_runtimeNode.end())
        {
            m_runtimeNode[objName] = CRuntimeNode{objName, {}};
        }
        return m_runtimeNode[objName];
    }
private:
    //保持所有对象
    std::map<std::string, CRuntimeNode> m_runtimeNode;
};

typedef Singleton<CRuntimeClass> CRuntimeClassAgent;

template<typename T>
class ClassRegistor
{
public:
    template<typename... Args >
    ClassRegistor(const char* objName, Args... args)
    {
        CObjectFactoryAgent::get_instance().RegisterObject<T>(objName);
        CRuntimeClassAgent::get_instance().RegisterInherit(objName, args...);
    }
private:
	void do_nothing(ClassRegistor const &) {}
};

#endif //__DYNAMICCREATE_H__